import { useContext, useMemo, useRef, useState, useEffect } from 'react'
/* 
    获取最新的state ，然后通过 mapStoreToState 得到订阅的state 判断
    订阅的state是否发生变化，如果发生变化渲染最新的state
*/
import { ReduxContext } from './useCreateStore'
function is(x, y) {
	return (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y)
}
const objectIs = (x, y) =>
	typeof Object.is === 'function' ? Object.is(x, y) : is(x, y)
const hasOwnProperty = Object.prototype.hasOwnProperty
function shallowEqual(objA, objB) {
	if (objectIs(objA, objB)) return true
	if (
		typeof objA !== 'object' ||
		objA === null ||
		typeof objB !== 'object' ||
		objB === null
	) {
		return false
	}

	const keysA = Object.keys(objA)
	const keysB = Object.keys(objB)
	if (keysA.length !== keysB.length) return false
	for (let i = 0; i < keysA.length; i++) {
		if (
			!hasOwnProperty.call(objB, keysA[i]) ||
			objectIs(objA[keysA[i]], objB[keysA[i]])
		)
			return false
	}

	return true
}

export default function useConnect(mapStoreToState = () => {}) {
	const contextValue = useContext(ReduxContext)
	const { dispatch, getInitState, subscribe, unSubscribe } = contextValue
	/* 初始化的 state */
	const stateValue = useRef(getInitState(mapStoreToState))
	const [, forceUpdate] = useState(null)

	// 产生
	const connectValue = useMemo(() => {
		const state = {
			/* 用于比较一次 dispatch中，新的state 和之前的state 是否发生变化 */
			cacheState: stateValue.current,
			// 更新函数
			update: function (newState) {
				/* 获取订阅的 state  */
				const selectState = mapStoreToState(newState)
				/* 浅比较 state 是否发生变化 */
				const isEqual = shallowEqual(state.cacheState, selectState)
				state.cacheState = selectState
				stateValue.current = selectState
				/* 更新 */
				if (!isEqual) {
					forceUpdate({})
				}
			},
		}

		return state
	}, [contextValue])
	useEffect(() => {
		/* 组件挂载-注册connect */
		const name = subscribe(connectValue)

		return () => {
			/* 组件卸载-解绑 connect */
			unSubscribe(name)
		}
	}, [connectValue])

	return [stateValue.current, dispatch]
}
